/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
 */

import { cloneDeep } from '@baize/wdk';
import { validateDataBySchema } from '@ohos/hvigor-common/src/util/json-schema-util.js';
import { HvigorErrorAdaptor } from '@ohos/hvigor-logger';
import { readJsonSync } from 'fs-extra';

import { HVIGOR_CONFIG_SCHEMA_PATH } from '../../common/const/path-const.js';
import { TrackAPI } from '../common/trace/hvigor-trace-factory.js';
import { AnalyzeModeKeyMap, coreParameter, CoreProperties, ParamValue } from '../internal/data/global-core-parameters.js';
import { HvigorLogger } from '../log/hvigor-log.js';
import { freezeDeep } from '../util/object-util.js';

export interface Parameter {
  getProperty(key: string): any | undefined;

  setProperty(key: string, value: any): void;

  getProperties(): Properties;

  getExtParam(key: string): string | undefined;

  getExtParams(): Record<string, string>;

  getStartParams(): StartParam;

  getWorkspaceDir(): string;
}

export interface ExternalStartParam {
  analyze: string | boolean;
  daemon: boolean;
  parallel: boolean;
  incremental: boolean;
  logLevel: string;
  typeCheck: boolean;
  optimizationStrategy: string;
  hotCompile?: boolean;
  hotReloadBuild?: boolean;
}

export type Properties = Readonly<CoreProperties>;
export type StartParam = Readonly<ExternalStartParam>;

export class ExternalParameter implements Parameter {
  private logger = HvigorLogger.getLogger(ExternalParameter.name);

  /**
   * hvigor-config-schema.json 中的 properties 字段 schema，只在 setProperty 中用来校验
   * 在第一次调用 setProperty 时才会赋值
   * @private
   */
  private propertiesSchema?: Record<string, any>;

  @TrackAPI getExtParam(key: string): string | undefined {
    return this.getExtParams()?.[key];
  }

  @TrackAPI getExtParams(): Readonly<Record<string, string>> {
    return freezeDeep(cloneDeep(coreParameter.extParams));
  }

  @TrackAPI getProperties(): Readonly<Record<string, ParamValue>> {
    return freezeDeep(cloneDeep(coreParameter.properties));
  }

  @TrackAPI getProperty(key: string): ParamValue {
    return this.getProperties()?.[key];
  }

  @TrackAPI setProperty(key: string, value: any) {
    if (!this.propertiesSchema) {
      this.propertiesSchema = readJsonSync(HVIGOR_CONFIG_SCHEMA_PATH).properties.properties;
    }

    const schemaKey = `${HVIGOR_CONFIG_SCHEMA_PATH}.properties.properties`;
    const { isValid, errMsg } = validateDataBySchema({ [key]: value }, schemaKey, this.propertiesSchema!);
    if (!isValid) {
      this.logger.printErrorExitWithoutStack('METHID_SETPROPERTY_VALIDATE_FAILED_IN_HVIGORFILE', [], [[errMsg]]);
    }

    coreParameter.properties[key] = value;
  }

  @TrackAPI getStartParams(): StartParam {
    return freezeDeep(
      cloneDeep({
        daemon: coreParameter.startParams.daemon,
        analyze: AnalyzeModeKeyMap.get(coreParameter.startParams.analyze)!,
        parallel: coreParameter.startParams.parallelExecution,
        incremental: coreParameter.startParams.incrementalExecution,
        logLevel: coreParameter.startParams.logLevel.levelStr.toLowerCase(),
        typeCheck: coreParameter.startParams.hvigorfileTypeCheck,
        optimizationStrategy: coreParameter.startParams.optimizationStrategy,
        hotCompile: coreParameter.startParams.hotCompile,
        hotReloadBuild: coreParameter.startParams.hotReloadBuild,
      }),
    );
  }

  @TrackAPI getWorkspaceDir(): string {
    return freezeDeep(cloneDeep(coreParameter.workspaceDir));
  }
}
